﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;

namespace FT
{
    /// <summary>
    /// cmd指令连接符：
    /// &	无条件执行&后的命令	cmd1 & cmd2 即cmd1，cmd2都会执行
    /// &&	成功后执行 cmd1 && cmd2 即若cmd1执行成功则执行cmd2
    /// ||	失败后执行 cmd1 || cmd2 即若cmd1执行失败则执行cmd2
    /// </summary>
    public class FTCmdConnector
    {
        private const char UnconditionalChar = '&';
        private const char SuccessContinueChar = '&';
        private const char FailedContinueChar = '|';

        public const string UnconditionalSymbol = "&";
        public const string SuccessContinueSymbol = "&&";
        public const string FailedContinueSymbol = "||";
    }

    /// <summary>
    /// cmd基础命令
    /// </summary>
    public class FTCmdBasicCommand
    {
        
    }

    public class FTCmd
    {
        private Thread cmdThread;

        public FTCmd()
        {

        }

        /// <summary>
        /// 主线程使用cmd执行命令
        /// </summary>
        public void RunCmd(string cmdArg, Action<string> callBack = null)
        {
            RunCmd("cmd.exe", cmdArg, callBack);//此cmd.exe是在Project目录下启动
        }

        /// <summary>
        /// 异步使用cmd执行命令
        /// </summary>
        public void ThreadRunCmd(string cmdArg, Action<string> callBack = null)
        {
            cmdThread = new Thread(new ThreadStart(() =>
            {
                RunCmd(cmdArg, callBack);
            }));
            Thread.Sleep(1000);
            cmdThread.Start();
        }

        public void RunCmd(List<string> cmdArgs, Action<string> callBack = null)
        {
            string cmdArg = "";
            foreach (var arg in cmdArgs)
            {
                cmdArg += arg + "&&";
            }
            cmdArg.TrimEnd('&');

            RunCmd(cmdArg, callBack);
        }

        public void ThreadRunCmd(List<string> cmdArgs, Action<string> callBack = null)
        {
            string cmdArg = "";
            foreach (var arg in cmdArgs)
            {
                cmdArg += arg + "&&";
            }
            cmdArg.TrimEnd('&');

            ThreadRunCmd(cmdArg, callBack);
        }

        public void RunCmd(List<string> cmdArgs, string connectSymbol, Action<string> callBack = null)
        {
            string cmdArg = "";
            foreach (var arg in cmdArgs)
            {
                cmdArg += arg + connectSymbol;
            }
            cmdArg.TrimEnd(connectSymbol[0]);

            RunCmd(cmdArg, callBack);
        }

        public void ThreadRunCmd(List<string> cmdArgs, string connectSymbol, Action<string> callBack = null)
        {
            string cmdArg = "";
            foreach (var arg in cmdArgs)
            {
                cmdArg += arg + connectSymbol;
            }
            cmdArg.TrimEnd(connectSymbol[0]);

            ThreadRunCmd(cmdArg, callBack);
        }

        /// <summary>
        /// 使用指定exe执行命令
        /// </summary>
        public void RunCmd(string fileExe, string cmdArg, Action<string> callBack = null)
        {
            if (string.IsNullOrEmpty(fileExe) || string.IsNullOrEmpty(cmdArg))
            {
                //UnityEngine.Debug.Log("Empty fileExe or cmdArg");
                throw new NotImplementedException("Empty fileExe or cmdArg");

                return;
            }

            cmdArg = "/c chcp 437&&" + cmdArg.Trim().TrimEnd('&') + "&exit";

            Process process = new Process();

            process.StartInfo.FileName = fileExe;
            process.StartInfo.Arguments = cmdArg;
            process.StartInfo.UseShellExecute = false;        //是否使用操作系统shell启动
            process.StartInfo.RedirectStandardOutput = true;  //由调用程序获取输出信息
            process.StartInfo.RedirectStandardError = true;   //重定向标准错误输出
            process.StartInfo.CreateNoWindow = true;          //不显示程序窗口

            process.OutputDataReceived += (sender, output) =>
            {
                callBack(output.Data);
            };

            process.ErrorDataReceived += (sender, error) =>
            {
                callBack(error.Data);
            };

            process.Start();

            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            process.WaitForExit();
            process.Close();
        }
    }
}